package com.xup.luckymoney.job;

import android.annotation.TargetApi;
import android.app.KeyguardManager;
import android.app.Notification;
import android.app.PendingIntent;
import android.content.Context;
import android.content.res.Resources;
import android.media.MediaPlayer;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.PowerManager;
import android.util.Log;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.Toast;

import com.xup.luckymoney.Config;
import com.xup.luckymoney.LuckyMoneyService;
import com.xup.luckymoney.R;

import java.util.List;

public abstract class BaseAccessibilityJob implements AccessibilityJob {

    private static final String TAG = "BaseAccessibilityJob";
    private static final boolean DEBUG = true;
    private static final String UNLOCK = "unLock";
    private static final int RELOCK_DELAY = 10000;

    public int stepKouLing = 0;
    private boolean grabEnd = true;
    private boolean needRelock = false;
    private boolean findTargetNode = false;
    private static Handler mHandler = new Handler(Looper.getMainLooper());
    private LuckyMoneyService service;
    // Strings in wechat
    public String getHongbao;
    // Strings in QQ
    public String clickToOpen, koulingHongbao, clickToInputKouling,
            send;
    protected long sDelayTime;
    private AccessibilityNodeInfo tempNode;
    private KeyguardManager.KeyguardLock keyguardLock;

    @Override
    public void onCreateJob(LuckyMoneyService service) {
        this.service = service;
        if (getHongbao == null) {
            Resources res = getContext().getResources();
            getHongbao = res.getString(R.string.get_hongbao);
            clickToOpen = res.getString(R.string.click_to_open);
            koulingHongbao = res.getString(R.string.kouling_hongbao);
            clickToInputKouling = res.getString(R.string.click_to_input_kouling);
            send = res.getString(R.string.send);
        }
        sDelayTime = getConfig().getWechatOpenDelayTime();
        KeyguardManager km = (KeyguardManager) service
                .getSystemService(Context.KEYGUARD_SERVICE);
        keyguardLock = km.newKeyguardLock(UNLOCK);
    }

    public Context getContext() {
        return service.getApplicationContext();
    }

    public Config getConfig() {
        return service.getConfig();
    }

    public LuckyMoneyService getService() {
        return service;
    }

    /**
     * open notification bar
     *
     * @param event
     * @return 1 if success, -1 if error
     */
    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
    public int openNotify(AccessibilityEvent event) {
        KeyguardManager mKeyguardManager = (KeyguardManager) getContext()
                .getSystemService(Context.KEYGUARD_SERVICE);
        if (mKeyguardManager.inKeyguardRestrictedInputMode()) {
            if (DEBUG) Log.d(TAG, "keyguard is showing, disable it.");
            needRelock = true;
            wakeUpAndUnlock();
        }
        if (event.getParcelableData() == null || !(event
                .getParcelableData() instanceof Notification)) {
            return -1;
        }
        stepKouLing = 0;
        grabEnd = false;

        Notification notification = (Notification) event.getParcelableData();
        PendingIntent pendingIntent = notification.contentIntent;

        try {
            pendingIntent.send();
            playLuckySound();
        } catch (Exception e) {
            e.printStackTrace();
            return -1;
        }
        return 1;
    }

    /**
     * sound alert
     */
    private void playLuckySound() {
        Config config = service.getConfig();
        boolean playSound = config.getNoticeEnable();
        Log.d(TAG, "playLuckySound(), " + playSound + ", config.musicIndex" + config.musicIndex);
        if (playSound) {
            config.playNotice();
        }
    }

    /**
     * when window state changed, begin sniff node
     */
    public void getPacket() {
        AccessibilityNodeInfo rootNode = getService().getRootInActiveWindow();
        recycle(rootNode);
    }

    public void recycle(final AccessibilityNodeInfo nodeInfo) {
        if (nodeInfo == null) {
            Log.e(TAG, "rootWindow is null");
            return;
        }

        int nodeCount = nodeInfo.getChildCount();
        if (nodeCount == 0) {
            if (nodeInfo.getText() != null) {
                String tagText = nodeInfo.getText().toString();
                if (DEBUG)
                    Log.d(TAG, "recycle, tagText = " + tagText + ", stepKouLing = " + stepKouLing);
                if (!isGrabEnd()) {
                    // kouling packet is special and need three steps to find different text
                    // step 1 and step 2 work immediately, but step 3 needs QQ enabled.
                    if ((stepKouLing == 0 && koulingHongbao.equals(tagText))
                            || (stepKouLing == 1 && clickToInputKouling.equals(tagText))) {
                        findTargetNode = true;
                        findClickableParent(nodeInfo);
                    } else if (/*getHongbao.equals(tagText) ||*/ (clickToOpen.equals(tagText)
                            || (stepKouLing == 2 && send.equals(tagText)))
                            && getConfig().getQQEnable()) {
                        findTargetNode = true;
                        getHandler().postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                findClickableParent(nodeInfo);
                            }
                        }, sDelayTime);
                    }
                }
            }
        } else {
            for (int i = nodeCount - 1; i >= 0; i--) {
                if (findTargetNode)
                    break;
                tempNode = nodeInfo.getChild(i);
                if (tempNode != null && !isGrabEnd()) {
                    recycle(tempNode);
                }
            }
        }
    }

    /**
     * find the clickable parent to perform click event
     *
     * @param info
     */
    protected void findClickableParent(AccessibilityNodeInfo info) {
        if (DEBUG) Log.d(TAG, "findClickableParent");
        String tagText = "";
        if (info == null) {
            Log.e(TAG, "findClickableParent(), node info is null");
            return;
        }
        CharSequence cText = info.getText();
        if (cText == null) {
            Log.e(TAG, "info text is null");
        }
        try {
            tagText = cText.toString();
        } catch (NullPointerException e) {
            Log.e(TAG, "tegText is null");
            // e.printStackTrace();
        }
        AccessibilityNodeInfo parent;
        if (info.isClickable()) {
            parent = info;
        } else {
            parent = info.getParent();
        }
        while (parent != null) {
            if (parent.isClickable()) {
                parent.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                findTargetNode = false;
                if (stepKouLing == 0 && koulingHongbao.equals(tagText)) {
                    stepKouLing = 1;
                    Log.d(TAG, "kouling, begin step 1");
                    getPacket();
                } else if (stepKouLing == 1 && clickToInputKouling.equals(tagText)) {
                    stepKouLing = 2;
                    Log.d(TAG, "kouling, begin step 2");
                    getPacket();
                }
                break;
            }
            parent = parent.getParent();
        }
    }

    @Override
    public void onStopJob() {
        if (mHandler != null)
            mHandler = null;
    }

    public Handler getHandler() {
        if (mHandler == null) {
            mHandler = new Handler(Looper.getMainLooper());
        }
        return mHandler;
    }

    private void closeHongbao(AccessibilityNodeInfo info) {
        if (getConfig().autoClosePacketInterface()) {
            if (isGrabEnd()) {
                List<AccessibilityNodeInfo> list = null;
                list = info.findAccessibilityNodeInfosByViewId(
                        "com.tencent.mobileqq:id/close_btn");
                if (list != null && !list.isEmpty()) {
                    AccessibilityNodeInfo node = list.get(0);
                    if (DEBUG) Log.d(TAG, "node.id = " + node.getWindowId());
                    if (node != null && node.isClickable()) {
                        node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                    }
                }
            }
        }
    }

    public void showToast(String str) {
        Toast.makeText(getContext(), str, Toast.LENGTH_LONG).show();
    }

    public void showToast(int strId) {
        Toast.makeText(getContext(), strId, Toast.LENGTH_LONG).show();
    }

    public void getHongbaoEnd() {
        Log.d(TAG, "getHongbaoEnd");
        grabEnd = true;
        if (needRelock)
            relockScreen();
    }

    public void wakeUpAndUnlock() {
        PowerManager pm = (PowerManager) service
                .getSystemService(Context.POWER_SERVICE);
        // get PowerManager.WakeLock object, the last parameter is a tag used in LogCat
        PowerManager.WakeLock wl = pm.newWakeLock(
                PowerManager.ACQUIRE_CAUSES_WAKEUP
                        | PowerManager.SCREEN_DIM_WAKE_LOCK, "bright");
        // light screen
        if (DEBUG) Log.d(TAG, "light scree and unlock");
        wl.acquire();
        keyguardLock.disableKeyguard();
        // release
        wl.release();
    }

    public void relockScreen() {
        Log.d(TAG, "relock screen after " + (RELOCK_DELAY / 1000) + " seconds.");
        getHandler().postDelayed(new Runnable() {
            @Override
            public void run() {
                if (DEBUG) Log.d(TAG, "relockScreen()");
                keyguardLock.reenableKeyguard();
            }
        }, RELOCK_DELAY);
    }

    public boolean isGrabEnd() {
        return grabEnd;
    }

    public int getRelockDelay() {
        return RELOCK_DELAY;
    }
}
